


let containers = {
    audio: false,
    video: {
        width: 640,
        height: 480,
    },
}

let offerOption = {

    offerToReceiveAudio:1,
    offerToReceiveVideo:1
}

let configuration = {}

let config = {

    iceServers: [
        {
            urls: "stun:stun2.l.google.com:19302"
        }
    ]
};

let server = null

function SendAnswerToUser(roomReferenceData, targetUserId, answer) {

    let message = {

        "header":{
            "msg_type":"send_answer_req",
            "room_id":roomReferenceData.roomId,
            "user_id":roomReferenceData.userId,
        },
        "content":{
            "type":answer.type,
            "sdp":answer.sdp,
            "user_id":targetUserId
        }
    }
    return JSON.stringify(message)
}

function GetPublishList(roomReferenceData) {

    let message = {

        "header":{
            "msg_type":"get_publish_list",
            "room_id":roomReferenceData.roomId,
            "user_id":roomReferenceData.userId
        },
        "content":{

        }
    }
    return JSON.stringify(message)
}

function PublishRequest(roomReferenceData, description, user_id) {

    let message = {

        "header":{

            "msg_type":"publish_req",
            "room_id":roomReferenceData.roomId,
            "user_id":roomReferenceData.userId
        },
        "content":{
            "type": description.type,
            "sdp": description.sdp,
            "user_id":user_id,
        }
    }
    return JSON.stringify(message)
}

function SubscribeRequest(roomReferenceData, userId) {

    let message = {

        "header":{

            "msg_type":"subscribe_req",
            "room_id":roomReferenceData.roomId,
            "user_id":roomReferenceData.userId
        },
        "content":{
            "subscribe_user_id":userId
        }
    }
    return JSON.stringify(message)
}

function IceCandidateInfo(roomReferenceData, icecandidate, user_id, sdpType) {

    let message = {

        "header":{

            "msg_type":"ice_candidate_req",
            "room_id":roomReferenceData.roomId,
            "user_id":roomReferenceData.userId

        },
        "content":{

            "candidate":icecandidate,
            "user_id":user_id,
            "sdp_type":sdpType
        }
    }
    return JSON.stringify(message)
}

function PublishStreamReq(roomReferenceData, status) {
    let message = {

        "header":{

            "msg_type":"publish_stream_req",
            "room_id":roomReferenceData.roomId,
            "user_id":roomReferenceData.userId
        },
        "content":{

            "status":status
        }
    }
    return JSON.stringify(message)
}

function GetPublishStreamStatusReq(roomReferenceData, userId) {

    let message = {

        "header":{

            "msg_type":"get_publish_stream_status_req",
            "room_id":roomReferenceData.roomId,
            "user_id":roomReferenceData.userId
        },
        "content":{

            "user_id":userId
        }
    }
    return JSON.stringify(message)
}

async function CreateLocalPeerConnection(roomReferenceData, user_id) {

    let user = null;
    for (let index in roomReferenceData.newUserList)
    {
        if (roomReferenceData.newUserList[index].userId === user_id)
        {
            user = roomReferenceData.newUserList[index];
            break
        }
    }
    if (user == null)
    {
        console.log("no found the user : " + user_id)
        return
    }
    user.localRtcConnection  = new RTCPeerConnection(config)

    roomReferenceData.localStream.getTracks().forEach(function (track) {

        user.localRtcConnection.addTrack(track, roomReferenceData.localStream)
    })

    user.localRtcConnection.addEventListener('track', function (event){

        let remote_video_tr = document.getElementById("remote_video_tr")
        let new_td = document.createElement("td");
        let new_div = document.createElement("div");
        new_div.style.width = "640px"
        new_div.style.height = "480px";
        new_div.style.backgroundColor = "lightslategrey"

        let new_video = document.createElement("video")

        if (new_video.srcObject === null) {

            new_video.srcObject = event.streams[0]
            new_video.play()
        }
        new_td.id = "table-" + user.userId;
        new_video.id = "video-" + user.userId;

        new_div.appendChild(new_video)
        new_td.appendChild(new_div)
        remote_video_tr.appendChild(new_td)
    })

    user.localRtcConnection.onicecandidate = function (event) {

        if (event.candidate == null) {

            return
        }
        if (event.candidate.type === "srflx")
        {
            user.selfCandidateArray.push(event.candidate);
        }
        else
        {
            // send icecandidate information to server
            PostMessageToWebsocket(IceCandidateInfo(roomReferenceData, event.candidate, user.userId, "offer"))
        }
    }
    user.localRtcConnection.onicegatheringstatechange = function (event) {

        if (event.target.iceGatheringState === "complete") {
            // change candidate
            for(let index in user.selfCandidateArray)
            {
                PostMessageToWebsocket(IceCandidateInfo(roomReferenceData, user.selfCandidateArray[index], user.userId, "offer"))
            }
            user.selfCandidateArray = []
            console.log(event);
        }
    }

    user.localRtcConnection.addEventListener('close', function (event) {

        console.log(event)
    })
    user.localRtcConnection.createOffer().then(function (description) {

        user.localRtcConnection.setLocalDescription(description)
        // send sdp message to server
        // send sdp offer to server
        PostMessageToWebsocket(PublishRequest(roomReferenceData, description, user_id))

    }).catch(function (error) {

        console.log("[createOffer] error msg : " + error)
    })
}

function gotLocalIceCandidate(event) {

    if (event.candidate == null) {

        return
    }
    // send icecandidate information to server
    PostMessageToWebsocket(IceCandidateInfo(roomReferenceData, event.candidate))
}

function PublishBroadcast(roomReferenceData, msg) {

    if (msg.content.user_id !== roomReferenceData.userId) {

        // roomReferenceData.mediaData.subscribeList.push(msg.content.user_id)

        for (let index in roomReferenceData.newUserList)
        {
            if (roomReferenceData.newUserList[index].userId === msg.content.user_id && roomReferenceData.newUserList[index].isSubscribe === false)
            {
                console.log("begin subscribe user id : " + msg.content.user_id)
                PostMessageToWebsocket(SubscribeRequest(roomReferenceData, msg.content.user_id))
                break
            }
        }
    }
}

async function SubscribeTarget(roomReferenceData, jsonMessage) {


    let userId = jsonMessage.content.subscribe_user_id;
    for (let index in roomReferenceData.newUserList)
    {
        let user = roomReferenceData.newUserList[index]
        if (user.userId === userId)
        {
            await CreateLocalPeerConnection(roomReferenceData, userId)
            break
        }
    }

}

async function SubscribeRes(roomReferenceData, message) {

    let user_id = message.content.from;

    console.log(roomReferenceData.newUserList)

    for (let index in roomReferenceData.newUserList)
    {
        let user = roomReferenceData.newUserList[index]
        if (user.userId === user_id)
        {
            user.peerRtcConnection = new RTCPeerConnection(config);

            if (roomReferenceData.localStream != null)
            {
                roomReferenceData.localStream.getTracks().forEach(function (track) {

                    user.peerRtcConnection.addTrack(track, roomReferenceData.localStream)
                })
            }
            user.peerRtcConnection.addEventListener('track', function (event){

                console.log("Received remote stream");
                let remote_video_tr = document.getElementById("remote_video_tr")
                let new_td = document.createElement("td");
                let new_div = document.createElement("div");
                new_div.style.width = "640px"
                new_div.style.height = "480px";
                new_div.style.backgroundColor = "lightslategrey"

                let new_video = document.createElement("video")

                if (new_video.srcObject === null) {

                    new_video.srcObject = event.streams[0]
                    new_video.play()
                }
                new_td.id = "table-" + user.userId;
                new_video.id = "video-" + user.userId;

                new_div.appendChild(new_video)
                new_td.appendChild(new_div)
                remote_video_tr.appendChild(new_td)
            })
            await user.peerRtcConnection.setRemoteDescription({type: 'offer', sdp: message.content.sdp})
            let answer = await user.peerRtcConnection.createAnswer()
            await user.peerRtcConnection.setLocalDescription(answer)
            user.peerRtcConnection.addEventListener('icecandidate', function (event) {

                if (event.candidate == null) {

                    return;
                }
                if (event.candidate.type === "srflx" && user.isSubscribe === false)
                {
                    user.userCandidateArray.push(event.candidate);
                }
                else
                {
                    console.log("remote icecandidate and send candidate")
                    PostMessageToWebsocket(IceCandidateInfo(roomReferenceData, event.candidate, user.userId, "answer"))
                }
            })
            user.peerRtcConnection.onicegatheringstatechange = function (event) {

                if (event.target.iceGatheringState === "complete") {

                    for (let index in user.userCandidateArray) {

                        PostMessageToWebsocket(IceCandidateInfo(roomReferenceData, user.userCandidateArray[index], user.userId, "answer"))
                    }
                    user.userCandidateArray = [];

                    console.log(event);
                }
            }
            // send answer msg to user_id
            PostMessageToWebsocket(SendAnswerToUser(roomReferenceData, user_id, answer))
            break
        }
    }
}

function PublishTarget(roomReferenceData, message) {

    SubscribeRes(roomReferenceData, message)
}

function CandidateTarget(roomReferenceData, message) {

    let candidateUuid = message.content.user_id

    let user = null
    for (let index in roomReferenceData.newUserList)
    {
        if (roomReferenceData.newUserList[index].userId === candidateUuid)
        {
            user = roomReferenceData.newUserList[index]
            break
        }
    }
    if (user == null)
    {
        return
    }
    if (message.content.sdp_type === "answer" && user.localRtcConnection != null) {

        console.log(message);
        try
        {
            user.localRtcConnection.addIceCandidate(message.content.candidate).then()
        }
        catch (e)
        {
            console.log(e)
        }

    } else if (message.content.sdp_type === "offer" && user.peerRtcConnection != null) {

        user.peerRtcConnection.addIceCandidate(message.content.candidate).then()
    }
}

function SetRemoteDescription(roomReferenceData, jsonMessage)
{
    let user = null
    for (let index in roomReferenceData.newUserList)
    {
        if (roomReferenceData.newUserList[index].userId === jsonMessage.content.user_id)
        {
            user = roomReferenceData.newUserList[index]
            break
        }
    }
    if (user == null)
    {
        return
    }

    if (jsonMessage.header.policy === 2)
    {
        user.localRtcConnection.setRemoteDescription({type:jsonMessage.content.type,sdp:jsonMessage.content.sdp}).then()
        user.isSubscribe = true
    }
    else
    {
        console.log("add candidate at [SetRemoteDescription] + candidate length : " + jsonMessage.content.candidate_list.length)
        for (let index in jsonMessage.content.candidate_list)
        {
            user.peerRtcConnection.addIceCandidate(jsonMessage.content.candidate_list[index]).then()
        }
        user.isSubscribe = true
    }
}

function GetPublishListResponse(roomReferenceData, message) {

    if (message.content.publish_list == null || message.content.publish_list.length === 0)
    {
        console.log("no publish user")
    }
    else
    {

    }
}

function PublishResponse(roomReferenceData, message)
{
    if (message.header.result === 0)
    {
        console.log("publish success!")
        let msg = GetPublishList(roomReferenceData)
        PostMessageToWebsocket(msg)
    }
}

function StopLocalMedia(roomReferenceData) {

    let localVideo = document.getElementById('local_video');
    localVideo.srcObject = null
    for (let index in roomReferenceData.newUserList)
    {
        let user = roomReferenceData.newUserList[index]
        if (user.localRtcConnection != null)
        {
            let remoteVideo = document.getElementById('video-' + user.userId);
            remoteVideo.srcObject = null
            user.localRtcConnection.close()
            user.localRtcConnection = null
        }
        if (user.peerRtcConnection != null)
        {
            let remoteVideo = document.getElementById('video-' + user.userId);
            remoteVideo.srcObject = null
            user.peerRtcConnection.close()
            user.peerRtcConnection = null
        }
        let table_data = document.getElementById("table-" + user.userId)
        if (table_data)
        {
            let table_manager = document.getElementById("remote_video_tr")
            table_manager.removeChild(table_data)
        }
        user.isSubscribe = false
    }
    roomReferenceData.newUserList = []
    if (roomReferenceData.localStream != null) {

        roomReferenceData.localStream.getTracks().forEach(track => track.stop());
        roomReferenceData.localStream = null
    }
}

function StopSubscribeStream(roomReferenceData, user_id) {

    for (let index in roomReferenceData.newUserList)
    {
        let user = roomReferenceData.newUserList[index]
        if (user.userId === user_id)
        {
            let remoteVideo = document.getElementById("video-" + user.userId);
            if (remoteVideo && remoteVideo.srcObject != null)
            {
                remoteVideo.srcObject = null
            }
            if (user.peerRtcConnection != null)
            {
                user.peerRtcConnection.close()
                user.peerRtcConnection = null
            }
            if (user.localRtcConnection != null)
            {
                user.localRtcConnection.close()
                user.localRtcConnection = null
            }
            user.isSubscribe = false
            let table_data = document.getElementById("table-" + user.userId)
            if (table_data)
            {
                let table_manager = document.getElementById("remote_video_tr")
                table_manager.removeChild(table_data)
            }
            break
        }
    }
}

function GetPublishStreamStatusRes(roomReferenceData, message) {

    let userId = message.content.user_id;
    for (let index in roomReferenceData.newUserList)
    {
        let user = roomReferenceData.newUserList[index]
        if (user.userId === userId)
        {
            console.log("user_id : " + userId, " status : " + message.content.status)
            user.status = message.content.status
            if (user.status === true)
            {
                // send subscribe req
                let msg = SubscribeRequest(roomReferenceData, userId)
                PostMessageToWebsocket(msg)
            }
            break
        }
    }
}























